<?php
/*
 * Created on
 * Date: 2007-11-28
 * Author: William Yang
 */

/*
 * Function array2object(): convert an array which contains key-value pairs to the object.
 * Key-value pair converts to the property-value pair in object.
 * 
 * Return value: the object converted out.
 */
abstract class Array2Object{
	
	/*
	 * Parameter:
	 * $alias: It's for table aliases while operating on multiple tables.
	 * In the $array, each key may contain the alias as the prefix literally.
	 * If $alias is not null, it must be appended to the property name for matching it in
	 * the $array.
	 */
	public function array2copy($array, $alias = null) {
		$retObj = clone $this;
		$obj = new ReflectionObject($retObj);
		$properties = $obj->getProperties();
		
		foreach ($properties as $p) {
    		$name = $p->getName();
    		/*
    		if ($alias != null)
    			$name = $alias.".".$name;
    		*/
    		if(array_key_exists($name, $array)) {
    			$p->setValue($retObj, $array[$name]);
    		}
		}
		return $retObj;
	}
}

/*
 * Function toArray(): convert the object itself to an array for database operation.
 */
abstract class ArraizeBase extends Array2Object{
	public function toArray() {
		$obj = new ReflectionObject($this);
		$properties = $obj->getProperties();
		
		$ret = array();
		foreach ($properties as $p) {
    		$name = $p->getName();
    		$value = $p->getValue($this);
    		
    		if($value === NULL) {
    			continue;
    		} else {
    			$ret[$name] = $value;
    		}
		}
		
		return $ret;
	}
}

abstract class ArraizableRegister extends ArraizeBase{
	/*
	 * Note that, if the table to insert contains the auto-incremented column, this function will
	 * return the generated ID. If database error accured, error code is returned. DbError::is_error() could
	 * be used to check whether the returned code is error.
	 * 
	 * If auto incremented ID is required, then if registration fails, -1 is returned, otherwise the ID is returned.
	 */
	public function register($config_file, $require_auto_incremented_uid = TRUE) {
		/*
		 * Get the information from parent class, then invoke database operator to create the object.
		 */
		$operator = new DatabaseOperator();
		$operator->config($config_file);
		
		$info = $this->toArray();
		
		$id = DbError::DB_OK;
		
		if (count($info)) {
			$id = $operator->insert($info, $require_auto_incremented_uid);
		} else {
			return DbError::NO_DB_OPERATION_NEEDED;
		}
		return $id;		
		/*
		if($require_auto_incremented_uid) {
			if (DbError::is_error($id))
				return -1;
			else
				return $id;
		} else {
			if (DbError::is_error($id))
				return -1;
			else
				return 0;
		}*/
	}
	
	/*
	 * Parameter:
	 * $uids: if it is of type array, it contains a list of UIDs, otherwise it's one single UID.
	 * 
	 * Return value:
	 * An array containing queried information
	 */
	public function query_by_uids($config_file, $uids) {
		/*
		 * Query information by the UID specified by $uid.
		 */
		
		$operator = new DatabaseOperator();
		$operator->config($config_file);
		
		$condList = new SqlCondList();
		if (gettype($uids) === gettype(array())) {
			$cnt = count($uids);
			for ($i = 0; $i < $cnt - 1; ++$i) {
				$condList->add_condition(new SqlCondition('uid', SqlCondition::EQUAL, $uids[$i]));
				$condList->add_relation(SqlCondition::_OR);
			}
			$condList->add_condition(new SqlCondition('uid', SqlCondition::EQUAL, $uids[$cnt - 1]));
		} else
			$condList->add_condition(new SqlCondition('uid', SqlCondition::EQUAL, $uids));
		
		$ret_array = $operator->select($condList);
		
		/*
		 * As the UID is unique, so only one row should be returned.
		 */
		if (count($ret_array) == 0) {
			return array();
		} else {
			return $ret_array;
		}
	}
}
?>
